﻿package fr.babos.graphic.medias 
{
	import com.greensock.TweenLite;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.PixelSnapping;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.net.URLRequest;
	import flash.system.ImageDecodingPolicy;
	import flash.system.LoaderContext;
	import fr.babos.utils.ArrayUtils;
	
	/**
	 * ...
	 * @author ZoulouX
	 */
	public class ImageLoader extends Sprite
	{
		public static const RESIZE_INSIDE		:String 		= "inside";
		public static const RESIZE_OUTSIDE		:String 		= "outside";
		public static const RESIZE_STRETCH		:String 		= "stretch";
		
		protected static var __bitmapsCache		:Array			= [];
		protected static var __bitmapsCacheURLs	:Array			= [];
		
		/**
		 * Les dimensions
		 */
		protected var _width					:int;
		protected var _height					:int;
		
		
		private var _url:String;
		
		/**
		 * Le loader
		 */
		protected var _loader					:Loader;
		
		/**
		 * Le bitmap
		 */
		protected var _bitmap					:Bitmap;
		
		/**
		 * Le type de redimentionnement
		 */
		protected var _resizeType				:String					= "inside";
		
		/**
		 * Si on doit lisser l'image
		 */
		protected var _smooth					:Boolean				= true;
		
		/**
		 * Si on doit faire une animation à la fin du chargement
		 */
		protected var _tweenOnComplete			:Boolean				= true;
		
		
		// Les getters
		public function get resizeType ():String
		{
			return _resizeType;
		}
		public function get smooth ():Boolean
		{
			return _smooth;
		}
		
		
		// Les setters
		public function set resizeType (value:String):void 
		{
			_resizeType = value;
		}
		public function set smooth (value:Boolean):void 
		{
			_smooth = value;
		}
		
		/**
		 * Animation sur la fin
		 */
		public function get tweenOnComplete ():Boolean 
		{
			return _tweenOnComplete;
		}
		
		public function set tweenOnComplete (value:Boolean):void 
		{
			_tweenOnComplete = value;
		}
		
		public function get bitmapData ():BitmapData
		{
			return null;
		}
		
		
		// Le constructeur
		public function ImageLoader (width:int = 50, height:int = 50, url:String = null, pResizeType:String = "")
		{
			if (pResizeType != "")
				_resizeType = pResizeType;
			
			// Enregistrer les dimentions
			_width = width;
			_height = height;
			
			addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
			
			// Si une URL est passée en paramètre, alors charger l'image
			if (url != null && url != "")
				load(url);
		}
		
		protected function removedFromStageHandler (e:Event):void 
		{
			removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
			
			if (_bitmap != null)
			{
				//_bitmap.bitmapData.dispose();
			}
			
			/*
			if (_loader != null)
			{
				try
				{
					_loader.close();
				}
				catch (e:Error)
				{
					
				}
			}
			*/
		}
		
		// La méthode pour charger le visuel
		public function load (url:String):void
		{
			// Vérifier que l'url ne soit pas nulle
			if (url != null)
			{
				_url = url;
				
				if (__bitmapsCache[_url] == null)
				{
					trace("Loading image", url);
					
					var loaderContext:LoaderContext = new LoaderContext();
					loaderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;
					loaderContext.allowCodeImport = false;
					
					// Créer le loader
					_loader = new Loader();
					
					// Ajouter les écouteur
					_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
					_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadErrorHandler);
					
					// Et charger
					_loader.load(new URLRequest(url), loaderContext);
					
					// Ajouter cette image
					//addChildAt(_loader, 0);
				}
				else
				{
					//trace("Image from cache", url);
					
					_bitmap = new Bitmap(__bitmapsCache[_url], PixelSnapping.ALWAYS);
					_bitmap.smoothing = _smooth;
					
					_bitmap.width = _width;
					_bitmap.height = _height;
					
					addChild(_bitmap);
				}
			}
		}
		
		protected function removeListeners ():void
		{
			_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadCompleteHandler);
			_loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, loadErrorHandler);
		}
		
		// Chargement réussi
		protected function loadCompleteHandler (e:Event):void
		{
			removeListeners();
			
			_bitmap = _loader.content as Bitmap;
			_bitmap.pixelSnapping = PixelSnapping.ALWAYS;
			
			// Redimentionner cette image
			if (_resizeType == "inside")
			{
				// Redimentionner avec des bordures
				if (_bitmap.width > _width)
				{
					_bitmap.width = _width;
					_bitmap.scaleY = _bitmap.scaleX;
				}
				if (_bitmap.height > _height)
				{
					_bitmap.height = _height;
					_bitmap.scaleX = _bitmap.scaleY;
				}
			}
			else if (_resizeType == "outside")
			{
				// Redimentionner sans bordures
				if (_bitmap.width < _width)
				{
					_bitmap.width = _width;
					_bitmap.scaleY = _bitmap.scaleX;
				}
				if (_bitmap.height < _height)
				{
					_bitmap.height = _height;
					_bitmap.scaleX = _bitmap.scaleY;
				}
			}
			else if (_resizeType == "stretch")
			{
				// Coller directement
				_bitmap.width = _width;
				_bitmap.height = _height;
			}
			
			// Centrer l'image
			if (_resizeType == "inside" || _resizeType == "outside" || _resizeType == "center")
			{
				_bitmap.x = _width / 2 - _bitmap.width / 2;
				_bitmap.y = _height / 2 - _bitmap.height / 2;
			}
			
			//
			_bitmap.smoothing = _smooth;
			
			addChild(_bitmap);
			
			
			__bitmapsCache[_url] = _bitmap.bitmapData;
			__bitmapsCacheURLs.push(_url);
			
			if (__bitmapsCacheURLs.length > 100)
			{
				var deletedURL:String = __bitmapsCacheURLs.shift();
				
				//trace("Deleting cache image", deletedURL, __bitmapsCacheURLs.length, __bitmapsCache.length, "items");
				
				if (__bitmapsCache[deletedURL] != null)
				{
					//(__bitmapsCache[deletedURL] as BitmapData).dispose();
					__bitmapsCache[__bitmapsCacheURLs[0]] = null;
					delete __bitmapsCache[deletedURL];
				}
				
				//__bitmapsCacheURLs.shift();
				//__bitmapsCacheURLs = ArrayUtils.deleteIndex(__bitmapsCacheURLs, 0);
			}
			
			
			//_loader.cacheAsBitmap = true;
			//_loader.cacheAsBitmapMatrix = new Matrix();
			
			// Ajouter cette image
			//addChildAt(_loader, 0);
			
			// Faire la tween
			if (_tweenOnComplete)
			{
				// Faire l'animation
				TweenLite.from(_loader, .4, {
					alpha: 0
				});
			}
			
			// Dispatcher l'event
			if (hasEventListener(Event.COMPLETE))
				dispatchEvent(new Event(Event.COMPLETE));
		}
		
		// Erreur de chargement
		protected function loadErrorHandler (e:IOErrorEvent):void
		{
			removeListeners();
			
			trace("IMAGE LOAD ERROR", _url, e.text);
			
			if (hasEventListener(IOErrorEvent.IO_ERROR))
				dispatchEvent(e);
		}
	}
}